#include <cstring>
#include "SDL/SDL.h"
#include "font_renderer.h"
#include "arial_28.h"
#include "arial_12.h"

class String {
public:
	class Tecken {
	public:
		char t;
		int at_x;
		int x_offset;
		int width;
	};
	Tecken tecken[512];
	int len;
	int width;
	
	String( const char* in, const unsigned char sizes[105], const unsigned char kerning[105][105] );
};

String::String( const char* in, const unsigned char sizes[105], const unsigned char kerning[105][105] ){
	static const char* giltigaTecken[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "å", "ä", "ö", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Å", "Ä", "Ö", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", ",", ";", ":", "<", ">", "|", "-", "_", "~", "'", "^", "ü", "Ü", "*", "§", "!", "\"", "@", "#", "£", "¤", "$", "%", "&", "/", "{", "(", "[", ")", "]", "=", "}", "?", "+", "\\", " "};
	
	len = 0;
	const char* ptr = in;
	while( *ptr != '\0' ){
		char tmp_tecken[3];
		int tecken_len;
		if( (*ptr & 0xE0) == 0xC0 ){
			tecken_len = 2;
			tmp_tecken[0] = *ptr++;
			tmp_tecken[1] = *ptr++;
			tmp_tecken[2] = '\0';
		} else {
			tecken_len = 1;
			tmp_tecken[0] = *ptr++;
			tmp_tecken[1] = '\0';
		}
		for( int i=0, at_x=0; i<105; i++ ){
			if( strcmp( tmp_tecken, giltigaTecken[i] ) == 0 ){
				tecken[len].t = i;
				tecken[len].at_x = at_x;
				if( len>0 ){
					int current, last;
					current = i;
					last = tecken[len-1].t;
					
					tecken[len].x_offset = tecken[len-1].x_offset + sizes[last] - kerning[last][current];
					tecken[len].width = sizes[current] - kerning[last][current];
					width += tecken[len].width;
				} else {
					tecken[len].x_offset = 0;
					width = sizes[i];
					tecken[len].width = width;
				}
				len++;
				break;
			}
			at_x += sizes[i];
		}
	}
}

template < typename RLEchar >
void Font::uncompressKerning( const RLEchar kerningk[], int len ){
	unsigned char* kerning_ = (unsigned char*)kerning;
	int pos = 0;
	for( int i=0; i<len; i++ ){
		for( int j=0; j<kerningk[i].antal; j++ )
			kerning_[pos++] = kerningk[i].v;
	}
}

Font::Font( int fontsize ){
	int hel_width = fontsize == 28 ? 1596 : 688;
	hel_height = fontsize == 28 ? 32 : 14;
	int num_pixels = fontsize == 28 ? 1596*32 : 688*14;
	unsigned const char* raw_pixels = fontsize == 28 ? arial_28_pixels : arial_12_pixels;
	sizes = fontsize == 28 ? arial_28_sizes : arial_12_sizes;
	unsigned int* pixels = new unsigned int[num_pixels];
	for( int i=0; i<num_pixels/8; i++ ){
		for( int j=0; j<8; j++ ){
			if( ((raw_pixels[i]>>j) & 1) == 1)
				pixels[i*8+j] = 0xffffff;
			else
				pixels[i*8+j] = 0;
		}
	}
	SDL_Surface* tmpbild = SDL_CreateRGBSurfaceFrom(pixels, hel_width, hel_height, 32, hel_width*4, 0xff, 0xff00, 0xff0000, 0xff000000);
	helFont = SDL_DisplayFormat( tmpbild );
	SDL_FreeSurface( tmpbild );
	SDL_SetColorKey( helFont, SDL_SRCCOLORKEY, SDL_MapRGB( helFont->format, 0, 0, 0 ) );
	delete pixels;
	
	if( fontsize == 28 )
		uncompressKerning<RLEchar28>( arial_28_kerning, 1045 );
	else
		uncompressKerning<RLEchar12>( arial_12_kerning, 1087 );
}

Font::~Font(){
	SDL_FreeSurface( helFont );
}


SDL_Surface* Font::renderText( const char* text, SDL_Color farg ){
	String s( text, sizes, kerning );
	SDL_Surface* surface = SDL_CreateRGBSurface( SDL_SWSURFACE, s.width, 32, 32, 0xff, 0xff00, 0xff0000, 0xff000000 );
	for( int i=0; i<s.len; i++ ) {
		SDL_Rect rect1 = {s.tecken[i].at_x, 0, sizes[(int)s.tecken[i].t], hel_height};
		SDL_Rect rect2 = {s.tecken[i].x_offset, 0, s.tecken[i].width, hel_height};
		SDL_BlitSurface( helFont, &rect1, surface, &rect2 );
	}
	return surface;
}
